import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.util.concurrent.Semaphore;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class AreaSelector {

    private JFrame frame;
    private AreaPanel areaPanel;
    
    private AreaSelector() throws AWTException {
        
        frame = new JFrame("");
        frame.setUndecorated(true);
        
        areaPanel = new AreaPanel(frame);
        frame.setLayout(new BorderLayout());
        frame.getContentPane().add(areaPanel, BorderLayout.CENTER);
        
        frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());
        frame.setLocationRelativeTo(null);
        frame.setAlwaysOnTop(true);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    private void waitSelect() {
    	areaPanel.waitSelect();
    	frame.dispose();
    }
    
    public static Rectangle getSelection() {
    	
    	AreaSelector selector = null;
    	
    	try {
            selector = new AreaSelector();
        } catch (AWTException e) {
            e.printStackTrace();
        } 
    	
    	selector.waitSelect();
    	return selector == null ? null : selector.getSelectedArea();
    }
    
    public Rectangle getSelectedArea() {
		return areaPanel.getArea();
	}
    
    public static void main(String[] args) {
        
        Rectangle rect = AreaSelector.getSelection();
        System.out.println(rect);
    }
}

class AreaPanel extends JPanel{
    
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private JFrame parentFrame = null;
	
    /**
     * Background image
     */
    private BufferedImage bgImage = null;
    
    /**
     * Foreground image
     */
    private BufferedImage fgImage = null;
    
    private Robot robot = null;
    
    private boolean drawRect = false;
    private Rectangle rect = new Rectangle(0, 0, 0, 0);
    
    private Rectangle selectedArea = null;
    private Semaphore selectedAreaNotify = new Semaphore(0);
    
    public AreaPanel(JFrame parentFrame) throws AWTException {
    	this.parentFrame = parentFrame;
        robot = new Robot();
        getImage();
        addMouseListener(new AreaMouseListener());
        addMouseMotionListener(new AreaMouseMotionListener());
    }
    
    public Rectangle getArea() {
    	return selectedArea;
    }
    
    private void getImage() {
        int color;
        int a, r, g, b;
        
        fgImage = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
        bgImage = new BufferedImage(fgImage.getWidth(), fgImage.getHeight(), fgImage.getType());
        int [] rgbArray = fgImage.getRGB(0, 0, bgImage.getWidth(), bgImage.getHeight(), null, 0, bgImage.getWidth());
        for(int i = 0; i < rgbArray.length; i++) {
            color = rgbArray[i];
            a = (color & 0xFF000000) >> 24;
            r = (color & 0x00FF0000) >> 16;
            g = (color & 0x0000FF00) >> 8;
            b = (color & 0x000000FF) >> 0;
            
            r /= 2;
            g /= 2;
            b /= 2;
            
            color = 0;
            color |= (a << 24) & 0xFF000000;
            color |= (r << 16) & 0x00FF0000;
            color |= (g << 8) & 0x0000FF00;
            color |= (b << 0) & 0x000000FF;
            
            rgbArray[i] = color;
        }
        bgImage.setRGB(0, 0, bgImage.getWidth(), bgImage.getHeight(), rgbArray, 0, bgImage.getWidth());
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        
        g.drawImage(bgImage, 0, 0, null);
        
        if(drawRect) {
            g.setColor(Color.GREEN);
            Rectangle tmpRect = new Rectangle(rect);
            if(tmpRect.width < 0) {
                tmpRect.x += tmpRect.width;
                tmpRect.width = -tmpRect.width;
            }
            if(tmpRect.height < 0) {
                tmpRect.y += tmpRect.height;
                tmpRect.height = -tmpRect.height;
            }
            g.drawImage(fgImage, 
                    tmpRect.x, tmpRect.y, 
                    tmpRect.x + tmpRect.width, tmpRect.y + tmpRect.height, 
                    tmpRect.x, tmpRect.y, 
                    tmpRect.x + tmpRect.width, tmpRect.y + tmpRect.height, 
                    null);
            g.drawRect(tmpRect.x, tmpRect.y, tmpRect.width, tmpRect.height);
        }
    }
    
    public void waitSelect() {
    	try {
			selectedAreaNotify.acquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    }
    
    class AreaMouseListener extends MouseAdapter {
        
        @Override
        public void mousePressed(MouseEvent e) {
            
            rect.x = e.getX();
            rect.y = e.getY();

            super.mousePressed(e);
        }
        
        @Override
        public void mouseReleased(MouseEvent e) {
            super.mouseReleased(e);
            
            if(!drawRect) {
            	selectedAreaNotify.release();
            } else {
                MyOptionDialog dialog = new MyOptionDialog(parentFrame, rect.x + rect.width, rect.y + rect.height);
                if(dialog.getOption()) {
                	selectedArea = rect;
                }
                selectedAreaNotify.release();
                dialog.dispose();
            }
        }
    }
    
    class AreaMouseMotionListener extends MouseMotionAdapter {
        @Override
        public void mouseDragged(MouseEvent e) {

            rect.width = e.getX() - rect.x;
            rect.height = e.getY() - rect.y;
            
            drawRect = true;
            AreaPanel.this.updateUI();
            
            super.mouseDragged(e);
        }
    }
}
